/*
  策略模式是一种行为设计模式，定义一系列算法，将每一个算法封装起来，并让它们可以相互替换。
  策略模式让算法独立于使用它的客户而变化，也称为政策模式（Policy）。
  学习参考文献：https://juejin.cn/post/7113451841001619463
*/

/*
 案例一：
    部分产品已预售：为鼓励客户预订，将在原价基础上享受 20% 的折扣。
    部分产品处于正常促销阶段：如果原价低于或等于100，则以10%的折扣出售；
    如果原价高于 100，则减 10 元。
    有些产品没有任何促销活动：它们属于 default 状态，并以原价出售。
    这时需要写一个获取商品价格的函数 getPrice ，应该怎么写呢？
*/

/*
    事实上，面对这样的问题，如果不考虑任何设计模式，
    最直观的写法可能 if-else 多次条件判断语句来计算价格。
*/

// originalPrice 价格
// status 状态  （1正常促销，2无促销 3预售）
function getPice(originalPrice, status) {
  if (status === 1) {
    if (originalPrice < 100) {
      return originalPrice * 0.9;
    } else {
      return originalPrice - 10;
    }
  }

  if (status === 2) {
    return originalPrice;
  }

  if (status === 3) {
    return originalPrice - 20;
  }
}

/*
    有三个条件，上面的代码写了三个 if 语句，这是非常直观的代码，但是这段代码组织上不好。
    首先，它违反了单一职责原则（Single responsibility principle，
    规定每个类或者函数都应该有一个单一的功能，并且该功能应该由这个类或者函数完全封装起来）。
    函数 getPrice 做了太多的事情，这个函数不易阅读，也容易出现 bug。如果一个条件出现 bug，
    整个函数就会崩溃。同时，这样的代码也不容易调试。
*/

/*
    策略模式修改：
*/
// status 状态  （promotionPrice正常促销，defaultPrice无促销 pre-sale预售  blackFridayPrice黑色星期五）
function getPice(originalPrice, status) {
  if (status === "pre-sale") {
    return preSalePrice(originalPrice);
  }

  if (status === "promotion") {
    return promotionPrice(originalPrice);
  }

  if (status === "black-friday") {
    return blackFridayPrice(originalPrice);
  }

  if (status === "default") {
    return defaultPrice(originalPrice);
  }
}

/**
 * 预售商品价格规则
 * @param {*} origialPrice
 * @returns
 */
function preSalePrice(originalPrice) {
  return originalPrice * 0.8;
}

/**
 * 促销商品价格规则
 * @param {*} origialPrice
 * @returns
 */
function promotionPrice(origialPrice) {
  if (origialPrice <= 100) {
    return origialPrice * 0.9;
  } else {
    return originalPrice - 20;
  }
}
/**
 * 黑色星期五促销规则
 * @param {*} origialPrice
 * @returns
 */
function blackFridayPrice(origialPrice) {
  if (origialPrice >= 100 && originalPrice < 200) {
    return origialPrice - 20;
  } else if (originalPrice >= 200) {
    return originalPrice - 50;
  } else {
    return originalPrice * 0.8;
  }
}
/**
 * 默认商品价格
 * @param {*} origialPrice
 * @returns
 */
function defaultPrice(origialPrice) {
  return origialPrice;
}

/*
 上面的逻辑我们使用策略模式进行了修改，虽然代码逻辑清晰了 
 但是如果有新添加的促销活动逻辑 我们还是需要手动去修改 getPrice函数体
 那么就不符合我们的函数体准则，我们可以继续优化
*/

const priceStrategies = {
  "pre-sale": preSalePrice,
  promotion: promotionPrice,
  "black-friday": blackFridayPrice,
  default: defaultPrice,
};

function getPice(originalPrice, status) {
  return priceStrategies[status](originalPrice);
}

/*
  优化后，我们即时以后再添加新逻辑，我们也不用在修改getPrice 只需要修改对应的映射即可 priceStrategies
*/
